<?php

namespace app\admin\controller;

use support\spark\model\system\AdminUser;
use support\Request;
use support\spark\exception\ApiException;
use support\View;
use Webman\Captcha\CaptchaBuilder;
use Webman\Captcha\PhraseBuilder;
use support\Response;
use support\exception\BusinessException;
use app\admin\common\Util;

class LoginController extends Curd
{

    /**
     * 不需要登录的方法
     * @var string[]
     */
    protected $noNeedLogin = ['login', 'logout', 'captcha','index','doLogin'];

    /**
     * 不需要鉴权的方法
     * @var string[]
     */
    protected $noNeedAuth = ['info'];

    /**
     * @var AdminUser
     */
    protected $model = null;

    public function __construct()
    {
        parent::__construct();
        $this->model = new AdminUser();
    }

    public function index(Request $request)
    {
        return view('login/index');

    }

    public function doLogin(Request $request)
    {
        $captcha = $request->post('code');
        if (strtolower($captcha) !== session('captcha-login')) {
            throw new ApiException('验证码错误');
        }
        $request->session()->forget('captcha-login');
        $username = $request->post('name', '');
        $password = $request->post('password', '');
        if (!$username) {
            throw new ApiException('用户名不能为空');
        }
       $this->checkLoginLimit($username);
        $admin = AdminUser::where('name', $username)->first();

        if (!$admin || ($admin->password != Util::makePassword($password, $admin->salt))) {
            throw new ApiException('账户不存在或密码错误');
        }
        if ($admin->status == 2) {
            throw new ApiException('当前账户暂时无法登录');
        }
        $admin->last_login_time = date('Y-m-d H:i:s');
        $admin->save();
        $this->removeLoginLimit($username);
        $admin = $admin->toArray();
        $session = $request->session();
        unset($admin['password']);
        $session->set('admin', $admin);
        return sparkSuccess(dataReturn(0,'登录成功', [
            'nickname' => $admin['nickname'],
            'token' => $request->sessionId(),
        ]));
    }
    /**
     * 退出
     * @param Request $request
     * @return Response
     */
    public function logout(Request $request): Response
    {
        $request->session()->delete('admin');
        return  redirect('/admin/login/index');
    }

    /**
     * 验证码
     * @param Request $request
     * @param string $type
     * @return Response
     */
    public function captcha(Request $request, string $type = 'login'): Response
    {
        $builder = new PhraseBuilder(4, 'abcdefghjkmnpqrstuvwxyzABCDEFGHJKMNPQRSTUVWXYZ');
        $captcha = new CaptchaBuilder(null, $builder);
        $captcha->build(120);
        $request->session()->set("captcha-$type", strtolower($captcha->getPhrase()));
        $img_content = $captcha->get();
        return response($img_content, 200, ['Content-Type' => 'image/jpeg']);
    }


    /**
     * 检查登录频率限制
     * @param $username
     * @return void
     * @throws BusinessException
     */
    protected function checkLoginLimit($username)
    {
        $limit_log_path = runtime_path() . '/login';
        if (!is_dir($limit_log_path)) {
            mkdir($limit_log_path, 0777, true);
        }
        $limit_file = $limit_log_path . '/' . md5($username) . '.limit';
        $time = date('YmdH') . ceil(date('i') / 5);
        $limit_info = [];
        if (is_file($limit_file)) {
            $json_str = file_get_contents($limit_file);
            $limit_info = json_decode($json_str, true);
        }

        if (!$limit_info || $limit_info['time'] != $time) {
            $limit_info = [
                'username' => $username,
                'count' => 0,
                'time' => $time
            ];
        }
        $limit_info['count']++;
        file_put_contents($limit_file, json_encode($limit_info));
        if ($limit_info['count'] >= 5) {
            throw new BusinessException('登录失败次数过多，请5分钟后再试');
        }
    }

    /**
     * 解除登录频率限制
     * @param $username
     * @return void
     */
    protected function removeLoginLimit($username)
    {
        $limit_log_path = runtime_path() . '/login';
        $limit_file = $limit_log_path . '/' . md5($username) . '.limit';
        if (is_file($limit_file)) {
            unlink($limit_file);
        }
    }


}
